'use strict';
import { app, protocol, BrowserWindow, globalShortcut, dialog, ipcMain } from 'electron';
import { createProtocol } from 'vue-cli-plugin-electron-builder/lib';
import { browserWindowOption, winURL, disabledKeys } from './config';
import { exec } from 'child_process';
import path from 'path';
import log from 'electron-log';
import { autoUpdater } from 'electron-updater';

const isDevelopment = process.env.NODE_ENV !== 'production';
const agreement = 'electron-playground-code'; // 自定义通用访问协议名
// 验证是否为自定义协议的链接
const AGREEMENT_REGEXP = new RegExp(`^${agreement}://`);
let win: BrowserWindow | null;
let webContents: any;
// 单例锁
const gotTheLock = app.requestSingleInstanceLock();

// 将计划注册为标准将允许通过文件系统 API访问文件。否则，渲染器将为计划抛出一个安全错误。
// 此方法只能在模块事件发出之前使用，并且只能调用一次。`ready app`
protocol.registerSchemesAsPrivileged([
  {
    scheme: 'app',
    privileges: {
      secure: true,
      standard: true
    }
  }
]);

autoUpdater.logger = log;
log.transports.file.level = 'info';
log.info('App starting...');

// 发送状态
function sendStatusToWindow(text: string) {
  log.info(text);
  if (win) {
    win.webContents.send('message', text);
  }
}

function createWindow() {
  // 如果有webpack启动的server
  if (process.env.WEBPACK_DEV_SERVER_URL) {
    win = new BrowserWindow(browserWindowOption());
    // 默认打开webpack启动的serve
    win.loadURL(process.env.WEBPACK_DEV_SERVER_URL);
    if (!process.env.IS_TEST) win.webContents.openDevTools();
  } else {
    const argv = process.argv[1];
    // 注册一个协议
    createProtocol('app');

    // 判断是否是新增
    if (argv === '--editor') {
      const editorWinOptions = browserWindowOption();
      win = new BrowserWindow(editorWinOptions);
      win.loadURL(`${winURL}#/editor`);
    } else {
      win = new BrowserWindow(browserWindowOption());
      win.loadURL(winURL);
    }
  }

  webContents = win.webContents;
  win.on('closed', () => {
    win = null;
  });

  setDefaultProtocol(); // 注册自定义协议
  autoUpdater.checkForUpdatesAndNotify(); // 自动检测更新
}

// 注册自定义协议
function setDefaultProtocol() {
  const agreement = 'electron-playground-code'; // 自定义协议名
  let isSet = false; // 是否注册成功

  app.removeAsDefaultProtocolClient(agreement); // 每次运行都删除自定义协议 然后再重新注册
  // 开发模式下在window运行需要做兼容
  if (process.env.NODE_ENV === 'development' && process.platform === 'win32') {
    // 设置electron.exe 和 app的路径
    isSet = app.setAsDefaultProtocolClient(agreement, process.execPath, [path.resolve(process.argv[1])]);
  } else {
    isSet = app.setAsDefaultProtocolClient(agreement);
  }
  console.log('是否注册成功', isSet);
}

// 控制单例
if (!gotTheLock) {
  app.quit();
} else {
  app.on('second-instance', () => {
    // 当运行第二个实例时,将会聚焦到mainWindow这个窗口
    if (win) {
      if (win.isMinimized()) {
        win.restore();
        win.minimize();
      }
    }
  });
}

// 监听自定义协议唤起
function watchProtocol() {
  if (!gotTheLock) {
    app.quit();
  } else {
    app.on('second-instance', (event, commandLine) => {
      // commandLine 是一个数组， 唤醒的链接作为数组的一个元素放在这里面
      commandLine.forEach(str => {
        if (AGREEMENT_REGEXP.test(str)) {
          console.log('获取协议链接, 根据参数做各种事情');
          dialog.showMessageBox({
            type: 'info',
            message: 'window protocol 自定义协议打开',
            detail: `自定义协议链接:${str}`
          });
        }
      });
    });
  }
}

ipcMain.on('window-min', function() {
  // 收到渲染进程的窗口最小化操作的通知，并调用窗口最小化函数，执行该操作
  if (win) {
    win.minimize();
  }
});

ipcMain.on('window-close', function() {
  app.quit();
});

app.on('ready', async () => {
  // 快捷键禁用
  for (const key of disabledKeys()) {
    // eslint-disable-next-line @typescript-eslint/no-empty-function
    globalShortcut.register(key, () => {});
  }
  // 创建窗口
  createWindow();
  // 监听协议
  watchProtocol();
});

app.on('window-all-closed', () => {
  if (process.platform !== 'darwin') {
    app.quit();
  }
});

app.on('activate', () => {
  if (win === null) {
    createWindow();
  }
});

if (isDevelopment) {
  if (process.platform === 'win32') {
    process.on('message', data => {
      if (data === 'graceful-exit') {
        app.quit();
      }
    });
  } else {
    process.on('SIGTERM', () => {
      app.quit();
    });
  }
}

// +++ 以下皆为新增内容
// 主进程监听渲染进程传来的信息
ipcMain.on('update', (e, arg) => {
  console.log(arg);
  checkForUpdates();
});

const checkForUpdates = () => {
  if (process.env.NODE_ENV === 'development') {
    autoUpdater.updateConfigPath = path.join(__dirname, 'latest.yml');
  }
  // 下面是自动更新的整个生命周期所发生的事件
  autoUpdater.on('error', function(message) {
    sendUpdateMessage('error', message);
  });
  autoUpdater.on('checking-for-update', function(message) {
    sendUpdateMessage('checking-for-update', message);
  });
  autoUpdater.on('update-available', function(message) {
    sendUpdateMessage('update-available', message);
  });
  autoUpdater.on('update-not-available', function(message) {
    sendUpdateMessage('update-not-available', message);
  });

  // 更新下载进度事件
  autoUpdater.on('download-progress', function(progressObj) {
    sendUpdateMessage('downloadProgress', progressObj);
  });
  // 更新下载完成事件
  autoUpdater.on('update-downloaded', function(
    event,
    releaseNotes,
    releaseName,
    releaseDate,
    updateUrl,
    quitAndUpdate
  ) {
    // sendUpdateMessage('isUpdateNow', '');
    ipcMain.on('updateNow', (e, arg) => {
      autoUpdater.quitAndInstall();
    });
  });
};

function sendUpdateMessage(message: string, data: any) {
  webContents.send('message', { message, data });
}
